package com.ispeed.fluttershensu;

import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.VpnService;
import android.os.ParcelFileDescriptor;
import android.text.TextUtils;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import gsdnsdk.Gsdnsdk;

/**
 * @author : timmy
 * @date : 2019/1/25
 */
public class LocalVPNService extends VpnService {

    public static LocalVPNService Instance;
    public static boolean IsRunning = false;
    private ExecutorService mExecutorService;
    private byte[] mPacket;


    private ParcelFileDescriptor mFileDescriptor;
    private FileOutputStream mFileOutputStream;

    /**
     * 10.0.0.2表示模拟器或者手机本机地址
     */
    public static final String VPN_ADDRESS = "10.0.2.2";
    /**
     * 路由地址0.0.0.0表示拦截所有从设备上发送出去的IP数据报
     */
    public static final String VPN_ROUTE = "0.0.0.0";
    private ServiceFlow mServiceFlow;
    private String mArguments;
    private String mAppPackageName;
    private String mImei;
    private long mRouteID;
    private long mDispatchType;
    private String mSystemVersion;
    private String mNetworkType;
    private String mGameId;

    public LocalVPNService() {
        Instance = this;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        IsRunning = true;
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mExecutorService = Executors.newFixedThreadPool(5);
        mExecutorService.execute(mISpeedRunnable);
    }


    private Runnable mISpeedRunnable = new Runnable() {
        @Override
        public void run() {
            try {
                //检查是否准备完毕。
                waitUntilPreapred();
                runVPN();

            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                dispose();
            }

        }

    };

    private void waitUntilPreapred() {
        SharedPreferences sharedPreferences = getSharedPreferences(getPackageName(), Context.MODE_PRIVATE);
        mArguments = sharedPreferences.getString("arguments", "");

        try {
            if (!TextUtils.isEmpty(mArguments)) {
                JSONObject jsonObject = new JSONObject(mArguments);
                mAppPackageName = jsonObject.optString("app_name");
                mDispatchType = jsonObject.optLong("dispatch_type", 0);
                mRouteID = jsonObject.optLong("routeID", 0);
                mImei = jsonObject.optString("imei");
                mGameId = jsonObject.optString("game_id");
                mSystemVersion = jsonObject.optString("systemVersion");
                mNetworkType = jsonObject.optString("networkType");
            }

        } catch (JSONException e) {
            e.printStackTrace();
        }

        while (prepare(this) != null) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private void runVPN() throws Exception {
        mPacket = new byte[20000];
        setupVpn();
        mFileDescriptor = establishVPN();

        mFileOutputStream = new FileOutputStream(mFileDescriptor.getFileDescriptor());
        FileInputStream fileInputStream = new FileInputStream(mFileDescriptor.getFileDescriptor());

        if (mServiceFlow == null) {
            mServiceFlow = new ServiceFlow(mFileOutputStream);
            long id1 = 1L;
            long id2 = 1L;
            Gsdnsdk.startGSDN(mServiceFlow, id1, id2);
        }

        int size = 0;
        while (size != -1 && IsRunning) {
            while ((size = fileInputStream.read(mPacket)) > 0 && IsRunning) {
                Gsdnsdk.inputPacket(mPacket);
            }
        }

        fileInputStream.close();
        disconnectVPN();
    }

    private void setupVpn() {
        // 网络类型
        Gsdnsdk.setSDKInfo(
                mImei,
                "liushuiwen",
                "android",
                mSystemVersion,
                "1.0.0.1",
                "0",
                "0",
                mGameId,
                "shensujiasuqi",
                mNetworkType
        );
    }

    final private int MTU = 1500;

    private ParcelFileDescriptor establishVPN() throws Exception {
        Builder builder = new Builder();
        builder.setMtu(MTU);
        builder.addDnsServer("8.8.8.8");
        builder.addAddress(VPN_ADDRESS, 32);
        builder.addRoute(VPN_ROUTE, 0);
        builder.setSession("神速加速器");
        builder.addAllowedApplication(mAppPackageName);
        return builder.establish();
    }

    public void disconnectVPN() {
        try {
            if (mFileDescriptor != null) {
                mFileDescriptor.close();
                mFileDescriptor = null;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        if (mServiceFlow != null) {
            this.mFileOutputStream = null;
            this.mServiceFlow = null;
            Gsdnsdk.stopGSDN();
        }
    }

    private synchronized void dispose() {
        // 断开VPN
        IsRunning = false;
        disconnectVPN();
        stopSelf();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mExecutorService != null) {
            mExecutorService.shutdownNow();
            mExecutorService = null;
        }
    }
}
